package cn.edu.xust.controller;


import cn.edu.xust.communication.AmmeterAutoReader;
import cn.edu.xust.communication.MyWaterReader;
import cn.edu.xust.communication.model.Result;
import cn.edu.xust.communication.remote.AmmeterRemoteReader;
import cn.edu.xust.communication.server.CommonOp;
import cn.edu.xust.configuration.exception.Default200Exception;
import cn.edu.xust.configuration.exception.ErrorConstant;
import cn.edu.xust.entity.*;
import cn.edu.xust.Ro.DeviceRo;
import cn.edu.xust.Ro.EleRo2;
import cn.edu.xust.Ro.WtRo2;
import cn.edu.xust.service.*;
import cn.edu.xust.util.R;
import cn.edu.xust.util.GenUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

import static cn.edu.xust.util.ValidUtils.signvertigy;


/**
 * 提供给对方的接口
 */
@Slf4j
@RestController()
@RequestMapping("/openapi")
public class openapiController {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private GatewayService gatewayService;
    @Autowired
    private ElecdataService elecdatas;
    @Autowired
    private WtdataService wtdataService;
    @Autowired
    private HotelService hotelService;


    /**
     * 酒店号房间号 查询电表号
     *
     * @param sign
     * @param jsonObject
     * @return
     * @throws Default200Exception
     */
    @ResponseBody
    @RequestMapping(value = "/devicelist")
    public R getdeviceid(@RequestParam(value = "sign") String sign,
                         @RequestParam(value = "appId") String appId,
                         @RequestParam(value = "timestamp") String timestamp,
                         @RequestParam(value = "rand") String rand,
                         @RequestParam(value = "requestId") String requestId,
                         @RequestBody JSONObject jsonObject) throws Default200Exception {
        vertify(sign, appId, timestamp, rand);
        String hotelid = jsonObject.getString("hotelid");
        String roomname = jsonObject.getString("roomname");

        //一个房间多个电表 查哪个 控制哪个？获取电表号的接口？
        List<DeviceEntity> deviceEntities = deviceService.getByHotelRoom(hotelid, roomname);

        ArrayList<DeviceRo> deviceEntities1 = new ArrayList<>();
        for (DeviceEntity d : deviceEntities) {
            DeviceRo deviceRo = new DeviceRo();
            deviceRo.setHotelid(String.valueOf(d.getHotelid()));
            deviceRo.setRoomname(d.getRoomname());
            deviceRo.setDeviceid(d.getName());
            deviceRo.setDevicename(d.getNickname());
            deviceEntities1.add(deviceRo);
        }
        return R.ok().put("data", deviceEntities1);
    }


    /**
     * 获取及时电表信息
     *
     * @param sign
     * @param jsonObject
     * @return
     * @throws Default200Exception
     */
    @ResponseBody
    @RequestMapping(value = "/ele/data")
    public R getdata(@RequestParam(value = "sign") String sign,
                     @RequestParam(value = "appId") String appId,
                     @RequestParam(value = "timestamp") String timestamp,
                     @RequestParam(value = "rand") String rand,
                     @RequestParam(value = "requestId") String requestId, @RequestBody JSONObject jsonObject) throws Default200Exception {
        //校验
        vertify(sign, appId, timestamp, rand);

        //取出数据
        String hotelid = jsonObject.getString("hotelid");
        String roomname = jsonObject.getString("roomname");

        //规定 ： 一个房间只有一个电表，1个或两个水表，热水和冷水   ele   coldwt  hotwt
        List<DeviceEntity> deviceEntities = deviceService.getByHotelRoomAngType(hotelid, roomname, "ele");
        if (deviceEntities.size() != 1) {
            log.info("酒店号:{},房间号:{},他的电表数量异常:{}", hotelid, roomname, deviceEntities.size());
            throw new Default200Exception(ErrorConstant.num_err,":"+deviceEntities.size()+"台");
        }
        //拿到电表
        DeviceEntity deviceEntity = deviceEntities.get(0);

        //拿到网关
        GatewayEntity gat = gatewayService.getById(deviceEntity.getGatewayid());
        if (gat == null) {
            log.info("配置的网关号不存在:{}", deviceEntity.getGatewayid());
            throw new Default200Exception(ErrorConstant.gateway_not_exsit);
        }

        //拿到ip
        String ip = gat.getIp();
        AmmeterAutoReader reader = new AmmeterAutoReader(ip, deviceEntity.getName());

        Result state = CommonOp.writeCommand(ip, GenUtils.genEleControlCmd(deviceEntity, "state"), UUID.randomUUID().toString());
        String states = GenUtils.parseExtraEleState(state);

        ElecdataEntity elecdataEntity = new ElecdataEntity();
        elecdataEntity.setGatewayid(gat.getId());
        elecdataEntity.setDeviceid(deviceEntity.getId());
        elecdataEntity.setVoltage(String.valueOf(reader.readCurrentVA()));
        elecdataEntity.setEleccurrent(String.valueOf(reader.readCurrentIA()));
        elecdataEntity.setElecwattage(String.valueOf(reader.readCurrentTotalActiveEnergy()));
        elecdataEntity.setDevicename(deviceEntity.getName());
        elecdataEntity.setState(states);
        elecdataEntity.setTimetype("manual-openapi");
        elecdataEntity.setCtime(new Date());
        if (elecdataEntity.getVoltage() != null && !elecdataEntity.getVoltage().equals("null")) {
            elecdatas.save(elecdataEntity);
        }
        return R.ok().put("data", elecdataEntity);
    }


    /**
     * 操作开关电表
     * status on off
     *
     * @return
     * @throws Default200Exception
     */
    @ResponseBody
    @RequestMapping(value = "/ele/control")
    public R operation(@RequestParam(value = "sign") String sign,
                       @RequestParam(value = "appId") String appId,
                       @RequestParam(value = "timestamp") String timestamp,
                       @RequestParam(value = "rand") String rand,
                       @RequestParam(value = "requestId") String requestId, @RequestBody JSONObject jsonObject) throws Default200Exception {
        //校验
        vertify(sign, appId, timestamp, rand);

        //取出数据
        String hotelid = jsonObject.getString("hotelid");
        String roomname = jsonObject.getString("roomname");
        String status = jsonObject.getString("status");

        //规定 ： 一个房间只有一个电表，1个或两个水表，热水和冷水   ele   coldwt  hotwt
        List<DeviceEntity> deviceEntities = deviceService.getByHotelRoomAngType(hotelid, roomname, "ele");
        if (deviceEntities.size() != 1) {
            log.info("酒店号:{},房间号:{},他的电表数量异常:{}", hotelid, roomname, deviceEntities.size());
            throw new Default200Exception(ErrorConstant.num_err,":"+deviceEntities.size()+"台");
        }
        //拿到电表
        DeviceEntity deviceEntity = deviceEntities.get(0);

        //拿到网关
        GatewayEntity gat = gatewayService.getById(deviceEntity.getGatewayid());
        if (gat == null) {
            log.info("配置的网关号不存在:{}", deviceEntity.getGatewayid());
            throw new Default200Exception(ErrorConstant.gateway_not_exsit);
        }

        //拿到ip
        String ip = gat.getIp();
        String cmd = GenUtils.genEleControlCmd(deviceEntity, status);
        log.info("生成指令:{}", cmd);
        Result result = CommonOp.writeCommand(ip, cmd, UUID.randomUUID().toString());
        String message = result.getMessage();
        if (message.startsWith("FEFEFE")) {
            return R.ok();
        }
        return R.error();
    }


    /**
     * 获取及时水表信息
     *
     * @param sign
     * @param jsonObject
     * @return
     * @throws Default200Exception
     */
    @ResponseBody
    @RequestMapping(value = "/wt/data")
    public R getwtdata(@RequestParam(value = "sign") String sign,
                       @RequestParam(value = "appId") String appId,
                       @RequestParam(value = "timestamp") String timestamp,
                       @RequestParam(value = "rand") String rand,
                       @RequestParam(value = "requestId") String requestId, @RequestBody JSONObject jsonObject) throws Default200Exception, InterruptedException {

        //校验
        vertify(sign, appId, timestamp, rand);

        //取出数据
        String hotelid = jsonObject.getString("hotelid");
        String roomname = jsonObject.getString("roomname");
        String type = jsonObject.getString("type");

        //规定 ： 一个房间只有一个电表，1个或两个水表，热水和冷水   ele   coldwt  hotwt
        List<DeviceEntity> deviceEntities = deviceService.getByHotelRoomAngType(hotelid, roomname, type);
        if (deviceEntities.size() != 1) {
            log.info("酒店号:{},房间号:{},他的电表数量异常:{}", hotelid, roomname, deviceEntities.size());
            throw new Default200Exception(ErrorConstant.num_err,":"+deviceEntities.size()+"台");
        }
        //拿到水表
        DeviceEntity deviceEntity = deviceEntities.get(0);

        //拿到网关
        GatewayEntity gat = gatewayService.getById(deviceEntity.getGatewayid());
        if (gat == null) {
            log.info("配置的网关号不存在:{}", deviceEntity.getGatewayid());
            throw new Default200Exception(ErrorConstant.gateway_not_exsit);
        }

        //拿到ip
        String ip = gat.getIp();
        MyWaterReader reader = new MyWaterReader(deviceEntity, ip);
        Result result = reader.readAll();
        deviceService.parsePersistwt(result.getMessage(), "manual-openapi");
        Thread.sleep(1000);
        WtdataEntity wtdataEntity = wtdataService.getnew(deviceEntity.getId());
        return R.ok().put("data", wtdataEntity);
    }

    private void vertify(@RequestParam("sign") String sign, @RequestParam("appId") String appId, @RequestParam("timestamp") String timestamp, @RequestParam("rand") String rand) throws Default200Exception {
        log.info(sign);
        String appsec="";
        //去数据库拿sec
        HotelEntity byAppid = hotelService.getByAppid(appId);
        if(byAppid==null){
            throw new Default200Exception(ErrorConstant.vertify_err);
        }else{
            appsec=byAppid.getAppsec();
        }
        boolean signvertigy = signvertigy(appId, appsec, rand, timestamp, sign);
        if (!signvertigy) {
            throw new Default200Exception(ErrorConstant.vertify_err);
        }
    }

    /**
     * 获取历史水表信息
     *
     * @param sign
     * @param jsonObject
     * @return
     * @throws Default200Exception
     */
    @ResponseBody
    @RequestMapping(value = "/wt/databytime")
    public R wtdatabytime(@RequestParam(value = "sign") String sign,
                          @RequestParam(value = "appId") String appId,
                          @RequestParam(value = "timestamp") String timestamp,
                          @RequestParam(value = "rand") String rand,
                          @RequestParam(value = "requestId") String requestId, @RequestBody JSONObject jsonObject) throws Default200Exception {
        //校验
        vertify(sign, appId, timestamp, rand);
        String date = jsonObject.getString("date");
        if (date == null) {
            throw new Default200Exception(ErrorConstant.date_need);

        }
        HotelEntity hotelEntity = hotelService.getByAppid(appId);
        if (hotelEntity == null) {
            throw new Default200Exception(ErrorConstant.hotel_not_found);
        }

        Integer hotelid = hotelEntity.getHotelId();
        List<DeviceEntity> devices = deviceService.getByHotelAndClassify(String.valueOf(hotelid), "wt");

        List<String> deivcenamelist = devices.stream().map(DeviceEntity::getName).collect(Collectors.toList());
        List<WtdataEntity> datas = wtdataService.getByDeviceNameAndTimetag(deivcenamelist, date);
        Map<String, WtdataEntity> datasmap = new HashMap<>();
        for (WtdataEntity wtdata : datas) {
            datasmap.put(wtdata.getDevicename(), wtdata);
        }

        ArrayList<WtRo2> wtRo2s = new ArrayList<>();
        for (DeviceEntity deviceEntity : devices) {
            WtRo2 wtRO = new WtRo2();
            String devicename = deviceEntity.getName();
            WtdataEntity data = datasmap.get(devicename);
            wtRO.setMac(devicename);
            wtRO.setHotcold(deviceEntity.getType().equals("coldwt") ? "冷水表" : "热水表");
            wtRO.setRoomid(deviceEntity.getRoomname());
            wtRO.setHotelid(String.valueOf(deviceEntity.getHotelid()));
            if (data == null) {
                log.info("没有查到{}:{}的水表数据", date, devicename);
                WtdataEntity wtdataEntity = wtdataService.searchNewstInHourtime(date, 6, devicename);
                if (wtdataEntity == null) {
                    WtdataEntity wtdataEntity1 = new WtdataEntity();
//                    wtdataEntity1.setCurrentcumulativeflow("0");
//                    wtdataEntity1.setAccumulatedtrafficday("0");
                    wtRO.setNote("noData");
                    data = wtdataEntity1;
                } else {
                    data = wtdataEntity;
                    wtRO.setNote("timeChanged");
                }
            }
            wtRO.setCurrentCumulativeflow(data.getCurrentcumulativeflow());
            wtRO.setAccumulatedTrafficDay(data.getAccumulatedtrafficday());
            wtRO.setLogtime(data.getCtime());
            wtRo2s.add(wtRO);
        }
        wtRo2s.sort(Comparator.comparing(WtRo2::getRoomid));
        return R.ok().put("data", wtRo2s);
    }


    /**
     * 获取历史电表信息
     *
     * @param sign
     * @param jsonObject
     * @return
     * @throws Default200Exception
     */
    @ResponseBody
    @RequestMapping(value = "/ele/databytime")
    public R eledatabytime(@RequestParam(value = "sign") String sign,
                           @RequestParam(value = "appId") String appId,
                           @RequestParam(value = "timestamp") String timestamp,
                           @RequestParam(value = "rand") String rand,
                           @RequestParam(value = "requestId") String requestId, @RequestBody JSONObject jsonObject) throws Default200Exception {
        //校验
        vertify(sign, appId, timestamp, rand);
        String date = jsonObject.getString("date");
        if (date == null) {
            throw new Default200Exception(ErrorConstant.date_need);
        }
        HotelEntity hotelEntity = hotelService.getByAppid(appId);
        if (hotelEntity == null) {
            throw new Default200Exception(ErrorConstant.hotel_not_found);
        }

        Integer hotelid = hotelEntity.getHotelId();
        List<DeviceEntity> devices = deviceService.getByHotelAndClassify(String.valueOf(hotelid), "ele");

        List<String> deivcenamelist = devices.stream().map(DeviceEntity::getName).collect(Collectors.toList());
        List<ElecdataEntity> datas = elecdatas.getByDeviceNameAndTimetag(deivcenamelist, date);
        Map<String, ElecdataEntity> datasmap = new HashMap<>();
        for (ElecdataEntity eledata : datas) {
            datasmap.put(eledata.getDevicename(), eledata);
        }

        ArrayList<EleRo2> eleRo2s = new ArrayList<>();
        for (DeviceEntity deviceEntity : devices) {
            EleRo2 eleRO = new EleRo2();
            String devicename = deviceEntity.getName();
            ElecdataEntity data = datasmap.get(devicename);
            eleRO.setMac(devicename);
            eleRO.setRoomid(deviceEntity.getRoomname());
            eleRO.setHotelid(String.valueOf(deviceEntity.getHotelid()));
            if (data == null) {
                log.info("没有查到{}:{}的电表数据", date, devicename);
                log.info("向上查询6小时内的最新数据");
                ElecdataEntity elecdataEntity = elecdatas.searchNewstInHourtime(date, 6, devicename);
                if (elecdataEntity == null) {
                    ElecdataEntity eledataEntity1 = new ElecdataEntity();
                    eleRO.setVoltage("0");
                    eleRO.setEleccurrent("0");
                    eleRO.setElecwattage("0");
                    eleRO.setState("off");
                    eleRO.setNote("noData");
                    data = eledataEntity1;
                } else {
                    data = elecdataEntity;
                    eleRO.setNote("timeChanged");
                }
            }
            eleRO.setVoltage(data.getVoltage());
            eleRO.setEleccurrent(data.getEleccurrent());
            eleRO.setElecwattage(data.getElecwattage());
            eleRO.setState(data.getState());
            eleRO.setLogtime(data.getCtime());
            eleRo2s.add(eleRO);
        }
        eleRo2s.sort(Comparator.comparing(EleRo2::getRoomid));
        return R.ok().put("data", eleRo2s);
    }


}
